/**
 * Copyright (c) 2010 Simple Graph Tools contributors. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * $Id$
 */
package org.sgt.coredef.util;

import java.util.Map;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.sgt.coredef.Chain;
import org.sgt.coredef.DecomposableNode;
import org.sgt.coredef.Edge;
import org.sgt.coredef.Node;

/**
 * @author Anne BUTTIGHOFFER <BR/>
 * <BR/>
 *         HISTORY :<BR/>
 *         <UL>
 *         <LI>Creation 090430 Anne BUTTIGHOFFER</LI>
 *         <LI>Added methods 090430 Frederick MINATCHY</LI>
 *         <LI>Refactored methods signature 090505 Anne BUTTIGHOFFER
 *         <UL>
 *         <LI>EList in extractNodesSequences map</LI>
 *         <LI>usage of Sequence rather than Steps</LI>
 *         </UL>
 *         </LI>
 *         <LI>Refactoring <B>090514</B> Anne BUTTIGHOFFER
 *         <UL>
 *         <LI>algo refactoring : making of original Map&lt;Route,
 *         Set&lt;Chain>> and working on chains. The idea is to recursively
 *         build DecomposableNodes to represent complex graphs between fork/join
 *         couples ; those DecomposableNodes are the handled by the dedicated
 *         policy generically to sequence each fork/join couples node
 *         appropriately.</LI>
 *         <LI>removed old alog methods.</LI>
 *         </UL>
 *         </LI>
 *         </UL>
 */
public interface IGraphSequencerPolicy {

	/**
	 * Creates and initializes (if needed) a proper IGraphSequence as needed by
	 * this policy.
	 * 
	 * @return IGraphSequence<?>
	 */
	IGraphSequence initSequence();

	/**
	 * Builds the graph sequence.
	 * 
	 * @param graphSequence
	 *            {@link IGraphSequence}.
	 * @param chainsByRoute
	 *            {@link Map<Route, Set<Chain>>}.
	 * @return true in case of success.
	 */
	boolean buildSequence(final IGraphSequence graphSequence,
			final Map<Route, Set<Chain>> chainsByRoute);

	/**
	 * Determines whether this SequencerPolicy should consider current node as a
	 * join node in the context of given Set of Chains.
	 * 
	 * @param node
	 *            {@link Node}.
	 * @param allChains
	 *            {@link Set<Chain>}.
	 * @return true only if node has to be considered a Join by current Policy.
	 */
	boolean isJoin(final Node node, final Set<Chain> allChains);

	/**
	 * Determines whether this SequencerPolicy should consider current node as a
	 * fork node in the context of given Set of Chains.
	 * 
	 * @param node
	 *            {@link Node}.
	 * @param allChains
	 *            {@link Set<Chain>}.
	 * @return true only if node has to be considered a Fork by current Policy.
	 */
	boolean isFork(final Node node, final Set<Chain> allChains);

	/**
	 * Determines whether this SequencerPolicy should consider current
	 * {@link Node} as a decision node in the context of given Set of Chains
	 * (i.e. both join and fork).
	 * 
	 * @param node
	 *            {@link Node}.
	 * @param allChains
	 *            {@link Set<Chain>}.
	 * @return true only if node has to be considered a Decision by current
	 *         Policy.
	 */
	boolean isDecision(final Node node, final Set<Chain> allChains);

	/**
	 * Determines whether this SequencerPolicy should consider current
	 * {@link Node} as a node to decompose (sequence). It is implementor's
	 * responsibility to ensure that a call to {@link #sequence(Node)} on the
	 * node is possible.
	 * 
	 * @param node
	 *            the {@link Node} to consider.
	 * @return true only if this Node can be decomposed (sequenced) by the
	 *         policy
	 */
	boolean isSequencable(final Node node);

	/**
	 * Creates an Edge which source is the given Node and destination is the
	 * given DecomposableNode.
	 * 
	 * @param source {@link Node}.
	 * @param decompNode {@link DecomposableNode}.
	 * @return an edge connecting the source and decompNode.
	 */
	Edge createEdge(final Node source, final DecomposableNode decompNode);

	/**
	 * Creates an Edge which destination is the given Node and source is the
	 * given DecomposableNode.
	 * 
	 * @param decompNode
	 *            {@link DecomposableNode}.
	 * @param destination
	 *            {@link Destination}.
	 * @return an edge connecting decompNode and destination.
	 */
	Edge createEdge(final DecomposableNode decompNode, final Node destination);

	/**
	 * Returns the set of node sequences this {@link Node} represents.
	 * 
	 * @param decompNode
	 *            the {@link Node} to sequence.
	 * @return the set of nodes list. It may be null, or empty.
	 */
	Set<EList<Node>> sequence(final Node decompNode);

	/**
	 * Returns the set of node sequences this Chain represents.
	 * 
	 * @param chain
	 *            {@link Chain}.
	 * @return the set of nodes list. It may be null, or empty.
	 */
	Set<EList<Node>> sequence(final Chain chain);

}
